package rpc

import (
	"container/list"
	"fmt"
	utils "gitee.com/ichub/goconfig/common/base/baseutils/stringutils"
	"gitee.com/ichub/gofactroy/common/ichubbase"
	"gitee.com/ichub/gofactroy/factroy/dbfactroy"
	"strings"
	"time"
)

type RpcFactroy struct {
}

func (rpc *RpcFactroy) BuildIf(columns *[]dbfactroy.COLUMNS) (lst *list.List) {

	s_default := `
	if param.Param.{{.goFieldName}} != nil {
		dbc = dbc.Where("{{.field_name}}=?", *param.Param.{{.goFieldName}})
	}`

	s_numeric := `
	if param.Param.{{.goFieldName}} != nil &&  *param.Param.{{.goFieldName}} != 0 {
		dbc = dbc.Where("{{.field_name}}=?", *param.Param.{{.goFieldName}})
	}`

	s_string := `
	if param.Param.{{.goFieldName}} != nil &&  *param.Param.{{.goFieldName}} != "" {
		dbc = dbc.Where("{{.field_name}}=?", *param.Param.{{.goFieldName}})
	}`
	s_datetime := `
	if param.Param.{{.goFieldName}} != nil   {
		dbc = dbc.Where("{{.field_name}}=?", daoInst.localDateFormat( *param.Param.{{.goFieldName}} ))
	}`

	lst = list.New()
	for _, v := range *columns {
		s := s_default
		if v.IfNumeric() {
			s = s_numeric
		} else if v.IfString() {
			s = s_string
		} else if v.IfLocalDateInt() {
			s = s_datetime
		}
		vars := make(map[string]interface{})
		//vars["table_name"] = v.TableName
		vars["field_name"] = v.COLUMN_NAME
		vars["goFieldName"] = utils.Case2Camel(v.COLUMN_NAME)

		wheres := utils.ParseTemplateString(s, vars)
		lst.PushBack(wheres)
	}

	return
}

func (rpc *RpcFactroy) buildProto2Model(columns *[]dbfactroy.COLUMNS) string {
	return utils.List2string(rpc.makeP2MLst(columns))
}

/*
   pbentity.Id = 0
   pbentity.Atimestamp = time.Time{}.Unix()
   pbentity.Column13 = ""
   pbentity.BitField = "false"*/

func (rpc *RpcFactroy) IniPbMsg(columns *[]dbfactroy.COLUMNS) *list.List {
	var DefaultVal map[string]string
	DefaultVal = make(map[string]string)

	DefaultVal["int64ToString"] = `"0"`
	DefaultVal["string"] = `""`
	DefaultVal["bool"] = `"false"`
	DefaultVal["int"] = "0"
	DefaultVal["time"] = "0"
	DefaultVal["timestr"] = "`1970-01-01 08:00:00`"

	s := `{{.Tab}}pbentity.{{.colname}} =  {{.DefaultValue}}`

	lst := list.New()
	for _, v := range *columns {
		vars := make(map[string]interface{})
		vars["colname"] = utils.Case2Camel(v.COLUMN_NAME)
		vars["Tab"] = fmt.Sprintf("\t\t")
		if v.IfInt64() {
			vars["DefaultValue"] = DefaultVal["int64ToString"]
		} else if v.IfBool() || v.IfBitField() {
			vars["DefaultValue"] = DefaultVal["bool"]
		} else if v.IfLocalDateInt() || v.IfLocalTimeInt() {
			vars["DefaultValue"] = DefaultVal["time"]
		} else if v.IfLocalDate() || v.IfLocalTime() {
			vars["DefaultValue"] = DefaultVal["time"]
		} else if v.IfString() {
			vars["DefaultValue"] = DefaultVal["string"]
		} else if v.IfInt() || v.IfNumeric() {
			vars["DefaultValue"] = DefaultVal["int"]
		}

		lst.PushBack(utils.ParseTemplateString(s, vars))

	}

	return lst
}

//PbMsg2Model
/*
 * entity.Id =  pbentity.GetId()
 * entity.Adate = basemodel.LocalDateInt{time.Unix(pbentity.GetAdate(), 0)}
 * entity.Atimestamp = basemodel.LocalTimeInt{time.Unix(pbentity.GetAtimestamp(), 0)}

 * entity.WorkState = entity.GetWorkState()
 * entity.BitField = pbentity.GetBitField() == "true"
 */
func (rpc *RpcFactroy) PbMsg2Model(columns *[]dbfactroy.COLUMNS) *list.List {

	s := `{{.Tab}} * entity.{{.colname}} =  pbentity.Get{{.colname}}()`
	s_int64string := `{{.Tab}} * entity.{{.colname}} =  utils.Str2Int64(pbentity.Get{{.colname}}())`

	s_date := `{{.Tab}} entity.{{.colname}} =  utils.Int64ToLocalDateIntPtr(pbentity.Get{{.colname}}())`
	s_datetime := `{{.Tab}} entity.{{.colname}} = utils.Int64ToLocalTimeIntPtr(pbentity.Get{{.colname}}())`
	s_datetimeUtc := `{{.Tab}} entity.{{.colname}} = utils.Int64ToLocalTimeIntUtcPtr(pbentity.Get{{.colname}}())`

	s_bool := `{{.Tab}} entity.{{.colname}} =  utils.Str2BoolPtr( pbentity.Get{{.colname}}() )`

	lst := list.New()
	for _, v := range *columns {
		colname := utils.Case2Camel(v.COLUMN_NAME)

		vars := make(map[string]interface{})
		vars["colname"] = colname
		vars["Tab"] = fmt.Sprintf("\t\t")
		ss := s
		if v.IfLocalDateInt() {
			ss = s_date
		} else if v.IfLocalTimeInt() {
			ss = s_datetime
		} else if v.IfLocalTimeUTCInt() {
			ss = s_datetimeUtc
		} else if v.IfBool() || v.IfBitField() {
			ss = s_bool
		} else if v.IfInt64() {
			ss = s_int64string
		}
		lst.PushBack(utils.ParseTemplateString(ss, vars))

	}

	return lst
}

func (rpc *RpcFactroy) Model2PbMsg(columns *[]dbfactroy.COLUMNS) *list.List {

	s := `{{.Tab}}pbentity.{{.colname}} =  entity.Get{{.colname}}()`
	s_time := `{{.Tab}}pbentity.{{.colname}} =  entity.Get{{.colname}}().Unix()`
	s_bool := `{{.Tab}}pbentity.{{.colname}} = utils.BoolPtr2Str( entity.{{.colname}} )`
	s_int64string := `{{.Tab}}pbentity.{{.colname}} =  utils.ToStr(entity.Get{{.colname}}())`

	lst := list.New()
	for _, v := range *columns {
		colname := utils.Case2Camel(v.COLUMN_NAME)

		vars := make(map[string]interface{})
		vars["colname"] = colname
		vars["Tab"] = fmt.Sprintf("\t\t")
		ss := s
		if v.IfLocalDateInt() || v.IfLocalTimeInt() || v.IfLocalTimeUTCInt() {
			ss = s_time
		} else if v.IfBool() {
			ss = s_bool
		} else if v.IfInt64() {
			ss = s_int64string
		}
		lst.PushBack(utils.ParseTemplateString(ss, vars))

	}

	return lst
}

func (rpc *RpcFactroy) makeP2MLst(columns *[]dbfactroy.COLUMNS) *list.List {

	s := `{{.Tab}}entity.{{.colname}} =  pbentity.{{.colname}}`

	lst := list.New()
	for _, v := range *columns {

		vars := make(map[string]interface{})
		vars["Tab"] = fmt.Sprintf("\t\t")
		vars["colname"] = utils.Case2Camel(v.COLUMN_NAME)
		lst.PushBack(utils.ParseTemplateString(s, vars))
	}

	utils.LogList(lst)
	return lst
}

func (rpc *RpcFactroy) buildRpc(tableTool *dbfactroy.DbFactroy) string {
	bs := dbfactroy.InstFileFactroy.ReadTemplateRpc()
	vars := make(map[string]interface{})

	vars["FileName"] = utils.Case2Camel(tableTool.Table) + "Rpc.go"
	vars["Description"] = "Rpc层" + utils.Case2Camel(tableTool.Table) + "Rpc"
	vars["Author"] = tableTool.Author
	vars["DATETIME"] = time.Now().Format(ichubbase.FormatDateTime)

	vars["ModelName"] = utils.Case2Camel(tableTool.Table)
	vars["LcModelName"] = utils.Lcfirst(utils.Case2Camel(tableTool.Table))
	vars["TableName"] = tableTool.Table
	vars["pkeyField"] = tableTool.Pkey
	vars["pkey"] = utils.Case2Camel(tableTool.Pkey)
	vars["pkeyType"] = tableTool.FindProtoType(tableTool.PkeyType)
	pkeyType := tableTool.FindGoType(tableTool.PkeyType)
	if strings.Contains(pkeyType, "int64") {
		vars["Int64IdRemark"] = ""
		vars["Int32IdRemark"] = "// "
	} else {
		vars["Int64IdRemark"] = "// "
		vars["Int32IdRemark"] = ""
	}

	columns := tableTool.FindCOLUMNS()

	vars["Model2PbMsg"] = utils.List2string(rpc.Model2PbMsg(columns))
	vars["IniPbMsg"] = utils.List2string(rpc.IniPbMsg(columns))
	vars["PbMsg2Model"] = utils.List2string(rpc.PbMsg2Model(columns))

	vars["Proto2Model"] = rpc.buildProto2Model(columns)
	vars["BuildWheres"] = utils.List2string(rpc.BuildIf(columns))

	return utils.ParseTemplateString(string(bs), vars)

}

func (rpc *RpcFactroy) BuildRpcFile(dbt *dbfactroy.DbFactroy) (dir, f, c string) {

	fbase := utils.Lcfirst(utils.Case2Camel(dbt.Table))

	dir = dbfactroy.Gendir_grpc
	f, c = fbase+"Rpc.go", rpc.buildRpc(dbt)
	dbfactroy.InstFileFactroy.WriteFileModuleRpc(dir, f, c)

	dbt.Dfcs = append(dbt.Dfcs, dbfactroy.DirFileContent{dir, f, c})

	return
}

func (rpc *RpcFactroy) Build(dbt *dbfactroy.DbFactroy) (dir, f, c string) {
	return rpc.BuildRpcFile(dbt)
}
